package com.mk.util;

import act.Act;
import com.mk.properties.AppConfig;
import io.netty.channel.nio.NioEventLoopGroup;
import org.osgl.util.S;
import org.redisson.Redisson;
import org.redisson.api.*;
import org.redisson.client.codec.Codec;
import org.redisson.config.Config;
import org.redisson.config.SingleServerConfig;

import java.util.concurrent.TimeUnit;

@SuppressWarnings("all")
public class Redis {
    /**
     * 用户信息
     */
    public static Client userDb;
    /**
     * 支付对象
     */
    public static Client payDb;
    /**
     * 其他
     */
    public static Client otherDb;

    @Deprecated
    public static void init() {
        userDb = factory(AppConfig.redis.user.get());
        payDb = factory(AppConfig.redis.pay.get());
        otherDb = factory(AppConfig.redis.other.get());
    }

    private static Client factory(Integer db) {
        Config config = new Config();
        int connectionMinimumIdleSize = 10;
        int idleConnectionTimeout = 10000;
        int pingTimeout = 1000;
        int connectTimeout = 10000;
        int retryAttempts = 3;
        int retryInterval = 1500;
        int subscriptionsPerConnection = 5;
        int timeout = 3000;
        int subscriptionConnectionMinimumIdleSize = 1;
        int subscriptionConnectionPoolSize = 50;
        int connectionPoolSize = 64;
        int dnsMonitoringInterval = 5000;
        int thread = 4;
        SingleServerConfig realConfig = config
            .setCodec(new org.redisson.codec.KryoCodec(Act.app().classLoader()))
            .setThreads(thread)
            .setEventLoopGroup(new NioEventLoopGroup())
            .useSingleServer()
            .setAddress("redis://" + AppConfig.redis.host.get() + ":" + AppConfig.redis.port.get())
            .setConnectionMinimumIdleSize(connectionMinimumIdleSize)
            .setConnectionPoolSize(connectionPoolSize)
            .setDatabase(db)
            .setDnsMonitoring(false)
            .setDnsMonitoringInterval(dnsMonitoringInterval)
            .setSubscriptionConnectionMinimumIdleSize(subscriptionConnectionMinimumIdleSize)
            .setSubscriptionConnectionPoolSize(subscriptionConnectionPoolSize)
            .setSubscriptionsPerConnection(subscriptionsPerConnection)
            .setRetryAttempts(retryAttempts)
            .setRetryInterval(retryInterval)
            .setTimeout(timeout)
            .setConnectTimeout(connectTimeout)
            .setIdleConnectionTimeout(idleConnectionTimeout)
            .setPingTimeout(pingTimeout);
        if (S.isNotBlank(AppConfig.redis.password.get())) {
            realConfig.setPassword(AppConfig.redis.password.get());
        }
        return new Client(Redisson.create(config));
    }

    public static class Client {
        private RedissonClient rclient;

        public Client(RedissonClient rclient) {
            this.rclient = rclient;
        }

        /**
         * Returns binary stream holder instance by <code>name</code>
         *
         * @param name of binary stream
         * @return BinaryStream object
         */
        public RBinaryStream getBinaryStream(String name) {
            return rclient.getBinaryStream(name);
        }

        /**
         * Returns geospatial items holder instance by <code>name</code>.
         *
         * @param <V>  type of value
         * @param name - name of object
         * @return Geo object
         */
        public <V> RGeo<V> getGeo(String name, Class<V> vClass) {
            return rclient.getGeo(name);
        }

        /**
         * Returns geospatial items holder instance by <code>name</code>
         * using provided codec for geospatial members.
         *
         * @param <V>   type of value
         * @param name  - name of object
         * @param codec - codec for value
         * @return Geo object
         */
        public <V> RGeo<V> getGeo(String name, Codec codec, Class<V> vClass) {
            return rclient.getGeo(name, codec);
        }

        /**
         * Returns set-based cache instance by <code>name</code>.
         * Supports value eviction with a given TTL value.
         *
         * <p>If eviction is not required then it's better to use regular map {@link #getSet(String, Codec)}.</p>
         *
         * @param <V>  type of value
         * @param name - name of object
         * @return SetCache object
         */
        public <V> RSetCache<V> getSetCache(String name, Class<V> vClass) {
            return rclient.getSetCache(name);
        }

        /**
         * Returns set-based cache instance by <code>name</code>.
         * Supports value eviction with a given TTL value.
         *
         * <p>If eviction is not required then it's better to use regular map {@link #getSet(String, Codec)}.</p>
         *
         * @param <V>   type of value
         * @param name  - name of object
         * @param codec - codec for values
         * @return SetCache object
         */
        public <V> RSetCache<V> getSetCache(String name, Codec codec, Class<V> vClass) {
            return rclient.getSetCache(name, codec);
        }

        /**
         * Returns map-based cache instance by <code>name</code>
         * using provided <code>codec</code> for both cache keys and values.
         * Supports entry eviction with a given MaxIdleTime and TTL settings.
         * <p>
         * If eviction is not required then it's better to use regular map {@link #getMap(String, Codec)}.
         *
         * @param <K>   type of key
         * @param <V>   type of value
         * @param name  - object name
         * @param codec - codec for keys and values
         * @return MapCache object
         */
        public <K, V> RMapCache<K, V> getMapCache(String name, Codec codec, Class<K> kClass, Class<V> vClass) {
            return rclient.getMapCache(name, codec);
        }

        /**
         * Returns map-based cache instance by <code>name</code>
         * using provided <code>codec</code> for both cache keys and values.
         * Supports entry eviction with a given MaxIdleTime and TTL settings.
         * <p>
         * If eviction is not required then it's better to use regular map {@link #getMap(String, Codec)}.
         *
         * @param <K>     type of key
         * @param <V>     type of value
         * @param name    - object name
         * @param codec   - codec for keys and values
         * @param options - map options
         * @return MapCache object
         */
        public <K, V> RMapCache<K, V> getMapCache(String name, Codec codec, MapOptions<K, V> options, Class<K> kClass, Class<V> vClass) {
            return rclient.getMapCache(name, codec, options);
        }

        /**
         * Returns map-based cache instance by name.
         * Supports entry eviction with a given MaxIdleTime and TTL settings.
         * <p>
         * If eviction is not required then it's better to use regular map {@link #getMap(String)}.</p>
         *
         * @param <K>  type of key
         * @param <V>  type of value
         * @param name - name of object
         * @return MapCache object
         */
        public <K, V> RMapCache<K, V> getMapCache(String name, Class<K> kClass, Class<V> vClass) {
            return rclient.getMapCache(name);
        }

        /**
         * Returns map-based cache instance by name.
         * Supports entry eviction with a given MaxIdleTime and TTL settings.
         * <p>
         * If eviction is not required then it's better to use regular map {@link #getMap(String)}.</p>
         *
         * @param <K>     type of key
         * @param <V>     type of value
         * @param name    - name of object
         * @param options - map options
         * @return MapCache object
         */
        public <K, V> RMapCache<K, V> getMapCache(String name, MapOptions<K, V> options, Class<K> kClass, Class<V> vClass) {
            return rclient.getMapCache(name, options);
        }

        /**
         * Returns object holder instance by name.
         *
         * @param <V>  type of value
         * @param name - name of object
         * @return Bucket object
         */
        public <V> RBucket<V> getBucket(String name, Class<V> v) {
            return rclient.getBucket(name);
        }

        /**
         * Returns object holder instance by name
         * using provided codec for object.
         *
         * @param <V>   type of value
         * @param name  - name of object
         * @param codec - codec for values
         * @return Bucket object
         */
        public <V> RBucket<V> getBucket(String name, Codec codec, Class<V> v) {
            return rclient.getBucket(name, codec);
        }

        /**
         * Returns interface for mass operations with Bucket objects.
         *
         * @return Buckets
         */
        public RBuckets getBuckets() {
            return rclient.getBuckets();
        }

        /**
         * Returns interface for mass operations with Bucket objects
         * using provided codec for object.
         *
         * @param codec - codec for bucket objects
         * @return Buckets
         */
        public RBuckets getBuckets(Codec codec) {
            return rclient.getBuckets(codec);
        }

        /**
         * Returns HyperLogLog instance by name.
         *
         * @param <V>  type of value
         * @param name - name of object
         * @return HyperLogLog object
         */
        public <V> RHyperLogLog<V> getHyperLogLog(String name, Class<V> v) {
            return rclient.getHyperLogLog(name);
        }

        /**
         * Returns HyperLogLog instance by name
         * using provided codec for hll objects.
         *
         * @param <V>   type of value
         * @param name  - name of object
         * @param codec - codec for values
         * @return HyperLogLog object
         */
        public <V> RHyperLogLog<V> getHyperLogLog(String name, Codec codec, Class<V> v) {
            return rclient.getHyperLogLog(name, codec);
        }

        /**
         * Returns list instance by name.
         *
         * @param <V>  type of value
         * @param name - name of object
         * @return List object
         */
        public <V> RList<V> getList(String name, Class<V> v) {
            return rclient.getList(name);
        }

        /**
         * Returns list instance by name
         * using provided codec for list objects.
         *
         * @param <V>   type of value
         * @param name  - name of object
         * @param codec - codec for values
         * @return List object
         */
        public <V> RList<V> getList(String name, Codec codec, Class<V> v) {
            return rclient.getList(name, codec);
        }

        /**
         * Returns List based Multimap instance by name.
         *
         * @param <K>  type of key
         * @param <V>  type of value
         * @param name - name of object
         * @return ListMultimap object
         */
        public <K, V> RListMultimap<K, V> getListMultimap(String name, Class<K> kClass, Class<V> vClass) {
            return rclient.getListMultimap(name);
        }

        /**
         * Returns List based Multimap instance by name
         * using provided codec for both map keys and values.
         *
         * @param <K>   type of key
         * @param <V>   type of value
         * @param name  - name of object
         * @param codec - codec for keys and values
         * @return ListMultimap object
         */
        public <K, V> RListMultimap<K, V> getListMultimap(String name, Codec codec, Class<K> kClass, Class<V> vClass) {
            return rclient.getListMultimap(name, codec);
        }

        /**
         * Returns List based Multimap instance by name.
         * Supports key-entry eviction with a given TTL value.
         *
         * <p>If eviction is not required then it's better to use regular map {@link #getSetMultimap(String)}.</p>
         *
         * @param <K>  type of key
         * @param <V>  type of value
         * @param name - name of object
         * @return ListMultimapCache object
         */
        public <K, V> RListMultimapCache<K, V> getListMultimapCache(String name, Class<K> kClass, Class<V> vClass) {
            return rclient.getListMultimapCache(name);
        }

        /**
         * Returns List based Multimap instance by name
         * using provided codec for both map keys and values.
         * Supports key-entry eviction with a given TTL value.
         *
         * <p>If eviction is not required then it's better to use regular map {@link #getSetMultimap(String, Codec)}.</p>
         *
         * @param <K>   type of key
         * @param <V>   type of value
         * @param name  - name of object
         * @param codec - codec for keys and values
         * @return ListMultimapCache object
         */
        public <K, V> RListMultimapCache<K, V> getListMultimapCache(String name, Codec codec, Class<K> kClass, Class<V> vClass) {
            return rclient.getListMultimapCache(name, codec);
        }

        /**
         * Returns local cached map instance by name.
         * Configured by parameters of options-object.
         *
         * @param <K>     type of key
         * @param <V>     type of value
         * @param name    - name of object
         * @param options - local map options
         * @return LocalCachedMap object
         */
        public <K, V> RLocalCachedMap<K, V> getLocalCachedMap(String name, LocalCachedMapOptions<K, V> options, Class<K> kClass, Class<V> vClass) {
            return rclient.getLocalCachedMap(name, options);
        }

        /**
         * Returns local cached map instance by name
         * using provided codec. Configured by parameters of options-object.
         *
         * @param <K>     type of key
         * @param <V>     type of value
         * @param name    - name of object
         * @param codec   - codec for keys and values
         * @param options - local map options
         * @return LocalCachedMap object
         */
        public <K, V> RLocalCachedMap<K, V> getLocalCachedMap(String name, Codec codec, LocalCachedMapOptions<K, V> options, Class<K> kClass, Class<V> vClass) {
            return rclient.getLocalCachedMap(name, codec, options);
        }

        /**
         * Returns map instance by name.
         *
         * @param <K>  type of key
         * @param <V>  type of value
         * @param name - name of object
         * @return Map object
         */
        public <K, V> RMap<K, V> getMap(String name, Class<K> kClass, Class<V> vClass) {
            return rclient.getMap(name);
        }

        /**
         * Returns map instance by name.
         *
         * @param <K>     type of key
         * @param <V>     type of value
         * @param name    - name of object
         * @param options - map options
         * @return Map object
         */
        public <K, V> RMap<K, V> getMap(String name, MapOptions<K, V> options, Class<K> kClass, Class<V> vClass) {
            return rclient.getMap(name, options);
        }

        /**
         * Returns map instance by name
         * using provided codec for both map keys and values.
         *
         * @param <K>   type of key
         * @param <V>   type of value
         * @param name  - name of object
         * @param codec - codec for keys and values
         * @return Map object
         */
        public <K, V> RMap<K, V> getMap(String name, Codec codec, Class<K> kClass, Class<V> vClass) {
            return rclient.getMap(name, codec);
        }

        /**
         * Returns map instance by name
         * using provided codec for both map keys and values.
         *
         * @param <K>     type of key
         * @param <V>     type of value
         * @param name    - name of object
         * @param codec   - codec for keys and values
         * @param options - map options
         * @return Map object
         */
        public <K, V> RMap<K, V> getMap(String name, Codec codec, MapOptions<K, V> options, Class<K> kClass, Class<V> vClass) {
            return rclient.getMap(name, codec, options);
        }

        /**
         * Returns Set based Multimap instance by name.
         *
         * @param <K>  type of key
         * @param <V>  type of value
         * @param name - name of object
         * @return SetMultimap object
         */
        public <K, V> RSetMultimap<K, V> getSetMultimap(String name, Class<K> kClass, Class<V> vClass) {
            return rclient.getSetMultimap(name);
        }

        /**
         * Returns Set based Multimap instance by name
         * using provided codec for both map keys and values.
         *
         * @param <K>   type of key
         * @param <V>   type of value
         * @param name  - name of object
         * @param codec - codec for keys and values
         * @return SetMultimap object
         */
        public <K, V> RSetMultimap<K, V> getSetMultimap(String name, Codec codec, Class<K> kClass, Class<V> vClass) {
            return rclient.getSetMultimap(name, codec);
        }

        /**
         * Returns Set based Multimap instance by name.
         * Supports key-entry eviction with a given TTL value.
         *
         * <p>If eviction is not required then it's better to use regular map {@link #getSetMultimap(String)}.</p>
         *
         * @param <K>  type of key
         * @param <V>  type of value
         * @param name - name of object
         * @return SetMultimapCache object
         */
        public <K, V> RSetMultimapCache<K, V> getSetMultimapCache(String name, Class<K> kClass, Class<V> vClass) {
            return rclient.getSetMultimapCache(name);
        }

        /**
         * Returns Set based Multimap instance by name
         * using provided codec for both map keys and values.
         * Supports key-entry eviction with a given TTL value.
         *
         * <p>If eviction is not required then it's better to use regular map {@link #getSetMultimap(String, Codec)}.</p>
         *
         * @param <K>   type of key
         * @param <V>   type of value
         * @param name  - name of object
         * @param codec - codec for keys and values
         * @return SetMultimapCache object
         */
        public <K, V> RSetMultimapCache<K, V> getSetMultimapCache(String name, Codec codec, Class<K> kClass, Class<V> vClass) {
            return rclient.getSetMultimapCache(name, codec);
        }

        /**
         * Returns semaphore instance by name
         *
         * @param name - name of object
         * @return Semaphore object
         */
        public RSemaphore getSemaphore(String name) {
            return rclient.getSemaphore(name);
        }

        /**
         * Returns semaphore instance by name.
         * Supports lease time parameter for each acquired permit.
         *
         * @param name - name of object
         * @return PermitExpirableSemaphore object
         */
        public RPermitExpirableSemaphore getPermitExpirableSemaphore(String name) {
            return rclient.getPermitExpirableSemaphore(name);
        }

        /**
         * Returns lock instance by name.
         * <p>
         * Implements a <b>non-fair</b> locking so doesn't guarantees an acquire order by threads.
         *
         * @param name - name of object
         * @return Lock object
         */
        public RLock getLock(String name) {
            return rclient.getLock(name);
        }

        /**
         * Returns lock instance by name.
         * <p>
         * Implements a <b>fair</b> locking so it guarantees an acquire order by threads.
         *
         * @param name - name of object
         * @return Lock object
         */
        public RLock getFairLock(String name) {
            return rclient.getFairLock(name);
        }

        /**
         * Returns readWriteLock instance by name.
         *
         * @param name - name of object
         * @return Lock object
         */
        public RReadWriteLock getReadWriteLock(String name) {
            return rclient.getReadWriteLock(name);
        }

        /**
         * Returns set instance by name.
         *
         * @param <V>  type of value
         * @param name - name of object
         * @return Set object
         */
        public <V> RSet<V> getSet(String name, Class<V> vClass) {
            return rclient.getSet(name);
        }

        /**
         * Returns set instance by name
         * using provided codec for set objects.
         *
         * @param <V>   type of value
         * @param name  - name of object
         * @param codec - codec for values
         * @return Set object
         */
        public <V> RSet<V> getSet(String name, Codec codec, Class<V> vClass) {
            return rclient.getSet(name, codec);
        }

        /**
         * Returns sorted set instance by name.
         * This sorted set uses comparator to sort objects.
         *
         * @param <V>  type of value
         * @param name - name of object
         * @return SortedSet object
         */
        public <V> RSortedSet<V> getSortedSet(String name, Class<V> vClass) {
            return rclient.getSortedSet(name);
        }

        /**
         * Returns sorted set instance by name
         * using provided codec for sorted set objects.
         * This sorted set sorts objects using comparator.
         *
         * @param <V>   type of value
         * @param name  - name of object
         * @param codec - codec for values
         * @return SortedSet object
         */
        public <V> RSortedSet<V> getSortedSet(String name, Codec codec, Class<V> vClass) {
            return rclient.getSortedSet(name, codec);
        }

        /**
         * Returns Redis Sorted Set instance by name.
         * This sorted set sorts objects by object score.
         *
         * @param <V>  type of value
         * @param name - name of object
         * @return ScoredSortedSet object
         */
        public <V> RScoredSortedSet<V> getScoredSortedSet(String name, Class<V> vClass) {
            return rclient.getScoredSortedSet(name);
        }

        /**
         * Returns Redis Sorted Set instance by name
         * using provided codec for sorted set objects.
         * This sorted set sorts objects by object score.
         *
         * @param <V>   type of value
         * @param name  - name of object
         * @param codec - codec for values
         * @return ScoredSortedSet object
         */
        public <V> RScoredSortedSet<V> getScoredSortedSet(String name, Codec codec, Class<V> vClass) {
            return rclient.getScoredSortedSet(name, codec);
        }

        /**
         * Returns String based Redis Sorted Set instance by name
         * All elements are inserted with the same score during addition,
         * in order to force lexicographical ordering
         *
         * @param name - name of object
         * @return LexSortedSet object
         */
        public RLexSortedSet getLexSortedSet(String name) {
            return rclient.getLexSortedSet(name);
        }

        /**
         * Returns topic instance by name.
         *
         * @param <M>  type of message
         * @param name - name of object
         * @return Topic object
         */
        public <M> RTopic<M> getTopic(String name, Class<M> mClass) {
            return rclient.getTopic(name);
        }

        /**
         * Returns topic instance by name
         * using provided codec for messages.
         *
         * @param <M>   type of message
         * @param name  - name of object
         * @param codec - codec for message
         * @return Topic object
         */
        public <M> RTopic<M> getTopic(String name, Codec codec, Class<M> mClass) {
            return rclient.getTopic(name, codec);
        }

        /**
         * Returns topic instance satisfies by pattern name.
         * <p>
         * Supported glob-style patterns:
         * h?llo subscribes to hello, hallo and hxllo
         * h*llo subscribes to hllo and heeeello
         * h[ae]llo subscribes to hello and hallo, but not hillo
         *
         * @param <M>     type of message
         * @param pattern of the topic
         * @return PatterTopic object
         */
        public <M> RPatternTopic<M> getPatternTopic(String pattern, Class<M> mClass) {
            return rclient.getPatternTopic(pattern);
        }

        /**
         * Returns topic instance satisfies by pattern name
         * using provided codec for messages.
         * <p>
         * Supported glob-style patterns:
         * h?llo subscribes to hello, hallo and hxllo
         * h*llo subscribes to hllo and heeeello
         * h[ae]llo subscribes to hello and hallo, but not hillo
         *
         * @param <M>     type of message
         * @param pattern of the topic
         * @param codec   - codec for message
         * @return PatterTopic object
         */
        public <M> RPatternTopic<M> getPatternTopic(String pattern, Codec codec, Class<M> mClass) {
            return rclient.getPatternTopic(pattern, codec);
        }

        /**
         * Returns unbounded queue instance by name.
         *
         * @param <V>  type of value
         * @param name of object
         * @return queue object
         */
        public <V> RQueue<V> getQueue(String name, Class<V> vClass) {
            return rclient.getQueue(name);
        }

        /**
         * Returns unbounded delayed queue instance by name.
         * <p>
         * Could be attached to destination queue only.
         * All elements are inserted with transfer delay to destination queue.
         *
         * @param <V>              type of value
         * @param destinationQueue - destination queue
         * @return Delayed queue object
         */
        public <V> RDelayedQueue<V> getDelayedQueue(RQueue<V> destinationQueue, Class<V> vClass) {
            return rclient.getDelayedQueue(destinationQueue);
        }

        /**
         * Returns unbounded queue instance by name
         * using provided codec for queue objects.
         *
         * @param <V>   type of value
         * @param name  - name of object
         * @param codec - codec for message
         * @return Queue object
         */
        public <V> RQueue<V> getQueue(String name, Codec codec, Class<V> vClass) {
            return rclient.getQueue(name, codec);
        }

        /**
         * Returns priority unbounded queue instance by name.
         * It uses comparator to sort objects.
         *
         * @param <V>  type of value
         * @param name of object
         * @return Queue object
         */
        public <V> RPriorityQueue<V> getPriorityQueue(String name, Class<V> vClass) {
            return rclient.getPriorityQueue(name);
        }

        /**
         * Returns priority unbounded queue instance by name
         * using provided codec for queue objects.
         * It uses comparator to sort objects.
         *
         * @param <V>   type of value
         * @param name  - name of object
         * @param codec - codec for message
         * @return Queue object
         */
        public <V> RPriorityQueue<V> getPriorityQueue(String name, Codec codec, Class<V> vClass) {
            return rclient.getPriorityQueue(name, codec);
        }

        /**
         * Returns unbounded priority blocking queue instance by name.
         * It uses comparator to sort objects.
         *
         * @param <V>  type of value
         * @param name of object
         * @return Queue object
         */
        public <V> RPriorityBlockingQueue<V> getPriorityBlockingQueue(String name, Class<V> vClass) {
            return rclient.getPriorityBlockingQueue(name);
        }

        /**
         * Returns unbounded priority blocking queue instance by name
         * using provided codec for queue objects.
         * It uses comparator to sort objects.
         *
         * @param <V>   type of value
         * @param name  - name of object
         * @param codec - codec for message
         * @return Queue object
         */
        public <V> RPriorityBlockingQueue<V> getPriorityBlockingQueue(String name, Codec codec, Class<V> vClass) {
            return rclient.getPriorityBlockingQueue(name, codec);
        }

        /**
         * Returns unbounded priority blocking deque instance by name.
         * It uses comparator to sort objects.
         *
         * @param <V>  type of value
         * @param name of object
         * @return Queue object
         */
        public <V> RPriorityBlockingDeque<V> getPriorityBlockingDeque(String name, Class<V> vClass) {
            return rclient.getPriorityBlockingDeque(name);
        }

        /**
         * Returns unbounded priority blocking deque instance by name
         * using provided codec for queue objects.
         * It uses comparator to sort objects.
         *
         * @param <V>   type of value
         * @param name  - name of object
         * @param codec - codec for message
         * @return Queue object
         */
        public <V> RPriorityBlockingDeque<V> getPriorityBlockingDeque(String name, Codec codec, Class<V> vClass) {
            return rclient.getPriorityBlockingDeque(name, codec);
        }

        /**
         * Returns priority unbounded deque instance by name.
         * It uses comparator to sort objects.
         *
         * @param <V>  type of value
         * @param name of object
         * @return Queue object
         */
        public <V> RPriorityDeque<V> getPriorityDeque(String name, Class<V> vClass) {
            return rclient.getPriorityDeque(name);
        }

        /**
         * Returns priority unbounded deque instance by name
         * using provided codec for queue objects.
         * It uses comparator to sort objects.
         *
         * @param <V>   type of value
         * @param name  - name of object
         * @param codec - codec for message
         * @return Queue object
         */
        public <V> RPriorityDeque<V> getPriorityDeque(String name, Codec codec, Class<V> vClass) {
            return rclient.getPriorityDeque(name, codec);
        }

        /**
         * Returns unbounded blocking queue instance by name.
         *
         * @param <V>  type of value
         * @param name - name of object
         * @return BlockingQueue object
         */
        public <V> RBlockingQueue<V> getBlockingQueue(String name, Class<V> vClass) {
            return rclient.getBlockingQueue(name);
        }

        /**
         * Returns unbounded blocking queue instance by name
         * using provided codec for queue objects.
         *
         * @param <V>   type of value
         * @param name  - name of queue
         * @param codec - queue objects codec
         * @return BlockingQueue object
         */
        public <V> RBlockingQueue<V> getBlockingQueue(String name, Codec codec, Class<V> vClass) {
            return rclient.getBoundedBlockingQueue(name, codec);
        }

        /**
         * Returns bounded blocking queue instance by name.
         *
         * @param <V>  type of value
         * @param name of queue
         * @return BoundedBlockingQueue object
         */
        public <V> RBoundedBlockingQueue<V> getBoundedBlockingQueue(String name, Class<V> vClass) {
            return rclient.getBoundedBlockingQueue(name);
        }

        /**
         * Returns bounded blocking queue instance by name
         * using provided codec for queue objects.
         *
         * @param <V>   type of value
         * @param name  - name of queue
         * @param codec - codec for values
         * @return BoundedBlockingQueue object
         */
        public <V> RBoundedBlockingQueue<V> getBoundedBlockingQueue(String name, Codec codec, Class<V> vClass) {
            return rclient.getBoundedBlockingQueue(name, codec);
        }

        /**
         * Returns unbounded deque instance by name.
         *
         * @param <V>  type of value
         * @param name - name of object
         * @return Deque object
         */
        public <V> RDeque<V> getDeque(String name, Class<V> vClass) {
            return rclient.getDeque(name);
        }

        /**
         * Returns unbounded deque instance by name
         * using provided codec for deque objects.
         *
         * @param <V>   type of value
         * @param name  - name of object
         * @param codec - codec for values
         * @return Deque object
         */
        public <V> RDeque<V> getDeque(String name, Codec codec, Class<V> vClass) {
            return rclient.getBlockingDeque(name, codec);
        }

        /**
         * Returns unbounded blocking deque instance by name.
         *
         * @param <V>  type of value
         * @param name - name of object
         * @return BlockingDeque object
         */
        public <V> RBlockingDeque<V> getBlockingDeque(String name, Class<V> vClass) {
            return rclient.getBlockingDeque(name);
        }

        /**
         * Returns unbounded blocking deque instance by name
         * using provided codec for deque objects.
         *
         * @param <V>   type of value
         * @param name  - name of object
         * @param codec - deque objects codec
         * @return BlockingDeque object
         */
        public <V> RBlockingDeque<V> getBlockingDeque(String name, Codec codec, Class<V> vClass) {
            return rclient.getBlockingDeque(name, codec);
        }

        /**
         * Returns atomicLong instance by name.
         *
         * @param name - name of object
         * @return AtomicLong object
         */
        public RAtomicLong getAtomicLong(String name) {
            return rclient.getAtomicLong(name);
        }

        /**
         * Returns atomicDouble instance by name.
         *
         * @param name - name of object
         * @return AtomicDouble object
         */
        public RAtomicDouble getAtomicDouble(String name) {
            return rclient.getAtomicDouble(name);
        }

        /**
         * Returns LongAdder instances by name.
         *
         * @param name - name of object
         * @return LongAdder object
         */
        public RLongAdder getLongAdder(String name) {
            return rclient.getLongAdder(name);
        }

        /**
         * Returns DoubleAdder instances by name.
         *
         * @param name - name of object
         * @return LongAdder object
         */
        public RDoubleAdder getDoubleAdder(String name) {
            return rclient.getDoubleAdder(name);
        }

        /**
         * Returns countDownLatch instance by name.
         *
         * @param name - name of object
         * @return CountDownLatch object
         */
        public RCountDownLatch getCountDownLatch(String name) {
            return rclient.getCountDownLatch(name);
        }

        /**
         * Returns bitSet instance by name.
         *
         * @param name - name of object
         * @return BitSet object
         */
        public RBitSet getBitSet(String name) {
            return rclient.getBitSet(name);
        }

        /**
         * Returns bloom filter instance by name.
         *
         * @param <V>  type of value
         * @param name - name of object
         * @return BloomFilter object
         */
        public <V> RBloomFilter<V> getBloomFilter(String name, Class<V> vClass) {
            return rclient.getBloomFilter(name);
        }

        /**
         * Returns bloom filter instance by name
         * using provided codec for objects.
         *
         * @param <V>   type of value
         * @param name  - name of object
         * @param codec - codec for values
         * @return BloomFilter object
         */
        public <V> RBloomFilter<V> getBloomFilter(String name, Codec codec, Class<V> vClass) {
            return rclient.getBloomFilter(name, codec);
        }

        /**
         * Returns script operations object
         *
         * @return Script object
         */
        public RScript getScript() {
            return rclient.getScript();
        }

        /**
         * Returns ScheduledExecutorService by name
         *
         * @param name - name of object
         * @return ScheduledExecutorService object
         */
        public RScheduledExecutorService getExecutorService(String name) {
            return rclient.getExecutorService(name);
        }

        /**
         * Returns ScheduledExecutorService by name
         * using provided codec for task, response and request serialization
         * <p>
         * Please use getExecutorService(String name, Codec codec) method instead.
         *
         * @param name  - name of object
         * @param codec - codec for task, response and request
         * @return ScheduledExecutorService object
         * @deprecated - use {@link #getExecutorService(String, Codec)} instead.
         */
        @Deprecated
        public RScheduledExecutorService getExecutorService(Codec codec, String name) {
            return rclient.getExecutorService(codec, name);
        }

        /**
         * Returns ScheduledExecutorService by name
         * using provided codec for task, response and request serialization
         *
         * @param name  - name of object
         * @param codec - codec for task, response and request
         * @return ScheduledExecutorService object
         * @since 2.8.2
         */
        public RScheduledExecutorService getExecutorService(String name, Codec codec) {
            return rclient.getExecutorService(name, codec);
        }

        /**
         * Returns object for remote operations prefixed with the default name (redisson_remote_service)
         *
         * @return RemoteService object
         */
        public RRemoteService getRemoteService() {
            return rclient.getRemoteService();
        }

        /**
         * Returns object for remote operations prefixed with the default name (redisson_remote_service)
         * and uses provided codec for method arguments and result.
         *
         * @param codec - codec for response and request
         * @return RemoteService object
         */
        public RRemoteService getRemoteService(Codec codec) {
            return rclient.getRemoteService(codec);
        }

        /**
         * Returns object for remote operations prefixed with the specified name
         *
         * @param name - the name used as the Redis key prefix for the services
         * @return RemoteService object
         */
        public RRemoteService getRemoteService(String name) {
            return rclient.getRemoteService(name);
        }

        /**
         * Returns object for remote operations prefixed with the specified name
         * and uses provided codec for method arguments and result.
         *
         * @param name  - the name used as the Redis key prefix for the services
         * @param codec - codec for response and request
         * @return RemoteService object
         */
        public RRemoteService getRemoteService(String name, Codec codec) {
            return rclient.getRemoteService(name, codec);
        }

        /**
         * Return batch object which executes group of
         * command in pipeline.
         * <p>
         * See <a href="http://redis.io/topics/pipelining">http://redis.io/topics/pipelining</a>
         *
         * @return Batch object
         */
        public RBatch createBatch() {
            return rclient.createBatch();
        }

        /**
         * Returns interface with methods for Redis keys.
         * Each of Redis/Redisson object associated with own key
         *
         * @return Keys object
         */
        public RKeys getKeys() {
            return rclient.getKeys();
        }

        /**
         * Returns RedissonAttachedLiveObjectService which can be used to
         * retrieve live REntity(s)
         *
         * @return LiveObjectService object
         */
        public RLiveObjectService getLiveObjectService() {
            return rclient.getLiveObjectService();
        }

        /**
         * Shutdown Redisson instance but <b>NOT</b> Redis server
         * <p>
         * This equates to invoke shutdown(0, 2, TimeUnit.SECONDS);
         */
        public void shutdown() {
            rclient.shutdown();
        }

        /**
         * Shuts down Redisson instance but <b>NOT</b> Redis server
         * <p>
         * Shutdown ensures that no tasks are submitted for <i>'the quiet period'</i>
         * (usually a couple seconds) before it shuts itself down.  If a task is submitted during the quiet period,
         * it is guaranteed to be accepted and the quiet period will start over.
         *
         * @param quietPeriod the quiet period as described in the documentation
         * @param timeout     the maximum amount of time to wait until the executor is {@linkplain #shutdown()}
         *                    regardless if a task was submitted during the quiet period
         * @param unit        the unit of {@code quietPeriod} and {@code timeout}
         */
        public void shutdown(long quietPeriod, long timeout, TimeUnit unit) {
            rclient.shutdown(quietPeriod, timeout, unit);
        }

        /**
         * Allows to get configuration provided
         * during Redisson instance creation. Further changes on
         * this object not affect Redisson instance.
         *
         * @return Config object
         */
        public Config getConfig() {
            return rclient.getConfig();
        }

        /**
         * Get Redis nodes group for server operations
         *
         * @return NodesGroup object
         */
        public NodesGroup<Node> getNodesGroup() {
            return rclient.getNodesGroup();
        }

        /**
         * Get Redis cluster nodes group for server operations
         *
         * @return ClusterNodesGroup object
         */
        public ClusterNodesGroup getClusterNodesGroup() {
            return rclient.getClusterNodesGroup();
        }

        /**
         * Returns {@code true} if this Redisson instance has been shut down.
         *
         * @return {@code true} if this Redisson instance has been shut down overwise <code>false</code>
         */
        public boolean isShutdown() {
            return rclient.isShutdown();
        }

        /**
         * Returns {@code true} if this Redisson instance was started to be shutdown
         * or was shutdown {@link #isShutdown()} already.
         *
         * @return {@code true} if this Redisson instance was started to be shutdown
         * or was shutdown {@link #isShutdown()} already.
         */
        public boolean isShuttingDown() {
            return rclient.isShuttingDown();
        }
    }
}
